// Header Protection
#ifndef _NOTIFICATION_H_
#define _NOTIFICATION_H_

/////////////////////////////////////////////////////////////////////////////////////
// When an event is raised, a notification is created and added to the queue of 
//     each registered event listener. 
class ABCNotification
{
public:     // methods

	inline ABCNotification() { }

	inline virtual ~ABCNotification() = 0 { }

	// Call process in the derived class, which has a specific type of listener and 
	//     event argument.
	// _pListener : IListener * - the event listener to process the event in
	virtual inline void Process( IListener *_pListener ) = 0;

private:    // dummy definitions
	ABCNotification( ABCNotification const & );
	ABCNotification &operator =( ABCNotification const & );
};

/////////////////////////////////////////////////////////////////////////////////////
// A notification for a specific type of listener and event argument.
// listener_t : template - the type of the listener for this notification
// eventarg_t : template - the type of event argument for this notification
template< class listener_t, class eventarg_t >
class CNotification : public ABCNotification
{
public:     // methods

	// _pArg : eventarg_t * - the event argument from the raised event
	// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler for the 
	//     raised event
	inline CNotification( 
		eventarg_t *_pArg, void (listener_t::*_pHandler)(eventarg_t &) ) : 
	m_pArg(_pArg), m_pHandler(_pHandler)
	{ m_pArg->AddRef(); }

	inline ~CNotification()
	{
		m_pArg->Release();
	}

	// Call the event handler from the listener with the event argument.
	// _pListener : IListener * - the event listener to process the event in
	inline void Process( IListener *_pListener )
	{
		( ((listener_t*)_pListener)->*m_pHandler )(*m_pArg);
	}

private:    // data
	eventarg_t *m_pArg;
	void (listener_t::*m_pHandler)(eventarg_t &);

private:    // dummy definitions
	CNotification( CNotification const & );
	CNotification &operator =( CNotification const & );
};

// Header Protection
#endif // _NOTIFICATION_H_
